package com.hlf.robot.utils;



import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author itzgyw
 * @Date 2020-01-31
 * @Time 0:25
 * @Description:
 */
public final class Strings {

    public static final String NULL_STR = "";
    /**
     * 下划线
     */
    private static final char SEPARATOR = '_';

    public static String toString(byte[] byteArray) {
        return new String(byteArray, StandardCharsets.UTF_8);
    }

    public static byte[] toByte(String data) {
        return data.getBytes(StandardCharsets.UTF_8);
    }

    public static byte[] encode(String data) {
        return encode(toByte(data));
    }

    public static String encodeToStr(String data) {
        return toString(encode(toByte(data)));
    }

    public static String encodeToStrNoWarp(String data) {
        return toString(encode(toByte(data))).replaceAll("[\\s*\t\n\r]", NULL_STR);
    }

    public static byte[] encode(byte[] data) {
        return Base64.getEncoder().encode(data);
    }

    public static byte[] encodeNoWarp(byte[] data) {
        byte[] noWarpByte = new byte[data.length];
        int count = 0;
        for (byte b : data) {
            if (b == 9 || b == 10 || b == 13) {
                count++;
                continue;
            }
            noWarpByte[noWarpByte.length] = b;
        }
        return Base64.getEncoder().encode(Arrays.copyOf(noWarpByte, noWarpByte.length - count));
    }

    public static String encodeToStr(byte[] data) {
        return toString(Base64.getEncoder().encode(data));
    }

    public static String encodeToStrNoWarp(byte[] data) {
        return encodeToStr(data).replaceAll("[\\s*\t\n\r]", NULL_STR);
    }

    public static byte[] decode(byte[] data) {
        return Base64.getDecoder().decode(data);
    }

    public static byte[] decode(String data) {
        return decode(toByte(data));
    }

    public static String url(String url, Map<?, ?> map) {
        if (map.isEmpty()) {
            return url;
        }
        StringBuilder builder = new StringBuilder(url);
        builder.append("?");
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            builder.append(urlEncode(String.valueOf(entry.getKey())));
            builder.append("=");
            builder.append(urlEncode(String.valueOf(entry.getValue())));
            builder.append("&");
        }
        if (!map.isEmpty()) {
            builder.deleteCharAt(builder.length() - 1);
        }

        return builder.toString();
    }

    public static String get(String str) {
        return getDefVal(str, NULL_STR);
    }

    public static <T> T getDefVal(T t, T def) {
        return t == null ? def : t;
    }


    public static String urlEncode(String data) {
//        return urlEncode(data, "UTF-8");
        return data;
    }

    public static String urlEncode(String data, String charset) {
        try {
            return URLEncoder.encode(data, charset);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static boolean isNotEmpty(Object... objs) {
        return !isEmpty(objs);
    }

    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    public static boolean isEmpty(Object... objs) {
        for (int index = 0; index < objs.length; index++) {
            Object obj = objs[index];
            if (isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        } else if (obj instanceof String) {
            return ((String) obj).trim().isEmpty();
        } else if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        } else if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        }
        return false;
    }


    public static boolean isNotEmpty(String... strs) {
        return !isEmpty(strs);
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }


    public static boolean isEmpty(String... strs) {
        for (int index = 0; index < strs.length; index++) {
            String str = strs[index];
            if (isEmpty(str)) {
                return true;
            }
        }
        return false;
    }

    public static boolean allIsEmpty(String... strs) {
        for (String str : strs) {
            if (!isEmpty(str)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    public static boolean isNotNull(Object obj) {
        return !isNull(obj);
    }

    public static boolean isNull(Object obj) {
        return obj == null;
    }


    public static String toString(Object obj) {
        return obj == null ? null : String.valueOf(obj);
    }


    public static String trim(String str) {
        return (str == null ? NULL_STR : str.trim());
    }


    /**
     * 驼峰转下划线命名
     */
    public static String toUnderScoreCase(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 前置字符是否大写
        boolean preCharIsUpperCase = true;
        // 当前字符是否大写
        boolean curreCharIsUpperCase = true;
        // 下一字符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i > 0) {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            } else {
                preCharIsUpperCase = false;
            }

            curreCharIsUpperCase = Character.isUpperCase(c);

            if (i < (str.length() - 1)) {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }

            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
                sb.append(SEPARATOR);
            } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs) {
        if (str != null && strs != null) {
            for (String s : strs) {
                if (str.equalsIgnoreCase(trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }

    public static Object cov(String str, Class classes) {
        switch (classes.getName()) {
            case "java.lang.String":
                return str;
            case "java.lang.Integer":
                return Integer.valueOf(str);
            case "java.lang.Long":
                return Long.valueOf(str);
            case "java.lang.Short":
                return Short.valueOf(str);
            case "java.lang.Byte":
                return Byte.valueOf(str);
            case "java.lang.Double":
                return Double.valueOf(str);
            case "java.lang.Float":
                return Float.valueOf(str);
            case "java.math.BigDecimal":
                return new BigDecimal(str);
            case "java.time.Boolean":
                str = str.toUpperCase();
                return str.equals("TRUE") ? Boolean.TRUE : Boolean.FALSE;
            case "java.time.LocalDate":
            case "java.time.LocalDateTime":
            case "java.time.LocalTime":
                throw new RuntimeException("未指定格式");
            case "int":
                return Integer.parseInt(str);
            case "long":
                return Long.parseLong(str);
            case "short":
                return Short.parseShort(str);
            case "byte":
                return Byte.parseByte(str);
            case "double":
                return Double.parseDouble(str);
            case "float":
                return Float.parseFloat(str);
            case "boolean":
                str = str.toUpperCase();
                return str.equals("TRUE") ? true : false;
            default:
                return null;
        }
    }

    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。 例如：HELLO_WORLD->HelloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String convertToCamelCase(String name) {
        return convertToCamelCase(name, "_");
    }

    public static String convertToCamelCase(String name, String spit) {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (name == null || name.isEmpty()) {
            // 没必要转换
            return "";
        } else if (!name.contains(spit)) {
            // 不含下划线，仅将首字母大写
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        // 用下划线将原始字符串分割
        String[] camels = name.split(spit);
        for (String camel : camels) {
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty()) {
                continue;
            }
            // 首字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }

    /**
     * 驼峰式命名法
     * 例如：user_name->userName
     */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }
        if (s.indexOf(SEPARATOR) == -1) {
            return s;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj) {
        return (T) obj;
    }

    public static String moneyFormat(String money) {
        int index = money.indexOf(".");
        if (index == -1) {
            return money + ".00";
        }
        int difference = money.length() - index;
        if (difference == 1) {
            return money + "00";
        } else if (difference == 2) {
            return money + "0";
        } else if (difference == 3) {
            return money;
        }
        String suffix = money.substring(index + 1);
        Integer suffixIntVal = new Integer(suffix);
        if (suffixIntVal > 0) {
            suffixIntVal = new BigDecimal(money.substring(index + 1, index + 3)).add(new BigDecimal(1)).intValue();
            String prefix = money.substring(0, index);
            if (suffixIntVal < 10) {
                return prefix + ".0" + suffixIntVal;
            }
            if (suffixIntVal >= 10 && suffixIntVal < 100) {
                return prefix + "." + suffixIntVal;
            } else {
                return new BigDecimal(prefix).add(new BigDecimal(1)).toString() + ".00";
            }

        } else {
            return money.substring(0, index + 3);
        }
    }


}
